﻿Imports System.ComponentModel
Imports System.Threading
Imports System.Collections.ObjectModel
Imports System.Text
Imports iConverter.Models
Imports iConverter.Core
Imports iConverter.Commands
Imports iConverter.Extensions

Namespace ViewModels


    Partial Public Class iConverterViewModel

        ''' <summary>
        ''' 注册窗口事件
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RegisterWindowsEvent()
            AddHandler Me._win.Closing, AddressOf Window_Closing
            AddHandler Me._win.Drop, AddressOf Window_Drop
            AddHandler Me._win.ContentRendered, AddressOf Window_ContentRendered
        End Sub


        ''' <summary>
        ''' 卸载窗口事件
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub UnRegisterWindowsEvent()
            RemoveHandler Me._win.Closing, AddressOf Window_Closing
            RemoveHandler Me._win.Drop, AddressOf Window_Drop
            RemoveHandler Me._win.ContentRendered, AddressOf Window_ContentRendered
        End Sub

#Region " 窗口关闭事件"

        Private Sub Window_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)


            Dim CloseDocumentResult As System.Windows.MessageBoxResult = CloseAllDocument()


            If CloseDocumentResult = MessageBoxResult.Cancel Then
                e.Cancel = True
            Else
                e.Cancel = False

                UnRegisterWindowsEvent()
            End If

        End Sub

#End Region

#Region "窗口拖放事件"

        Private Sub Window_Drop(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs)


            Dim dataobj = TryCast(e.Data, DataObject)


            If dataobj IsNot Nothing AndAlso dataobj.ContainsFileDropList Then

                Dim filelists = dataobj.GetFileDropList


                For Each filename In filelists
                    OpenDocument(filename)

                Next

            End If




        End Sub

#End Region

#Region "窗体 加载 事件"

        Private Sub Window_ContentRendered(ByVal sender As Object, ByVal e As EventArgs)

            '初次启动
            If SettingManager.Settings.EncodingList.Count = 0 Then


                '启动设置
                iConverterCommands.SettingsCommand.Execute(OptionTabs.General, Me._win)

            End If

        End Sub

#End Region


        ''' <summary>
        ''' 注册 Command Bindings
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RegisterCommandBindings()



            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.[New], AddressOf OnExecuteNew, AddressOf OnCanExecuteNew))
            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.Open, AddressOf OnExecuteOpen, AddressOf OnCanExecuteOpen))
            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.Close, AddressOf OnExecuteClose, AddressOf OnCanExecuteClose))
            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.Save, AddressOf OnExecuteSave, AddressOf OnCanExecuteSave))
            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.SaveAs, AddressOf OnExecuteSaveAs, AddressOf OnCanExecuteSaveAs))

            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.SaveADVCommand, AddressOf OnExecuteSaveADV, AddressOf OnCanExecuteSaveADV))

            Me._win.CommandBindings.Add(New CommandBinding(ApplicationCommands.Help, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.StartUseCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.CheckUpdateCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.WebSiteCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.PendingRequestCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.FeedbackCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ContactusCommand, AddressOf OnExecuteOpenLink, AddressOf OnCanExecuteOpenLink))


            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.SettingsCommand, AddressOf OnExecuteSettingsCommand, AddressOf OnCanExecuteSettingsCommand))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ShowVersionAndCopyRightInfoCommand, AddressOf OnExecuteShowVersionAndCopyRightInfoCommand, AddressOf OnCanExecuteShowVersionAndCopyRightInfoCommand))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ShowLicenseInfoCommand, AddressOf OnExecuteShowLicenseInfoCommand, AddressOf OnCanExecuteShowLicenseInfoCommand))


            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ConvertCommand, AddressOf OnExecuteConvertCommand, AddressOf OnCanExecuteConvertCommand))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.BatchConvertCommand, AddressOf OnExecuteBatchConvertCommand, AddressOf OnCanExecuteBatchConvertCommand))

            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ExitCommand, AddressOf OnExecuteExit, AddressOf OnCanExecuteExit))
            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.SendCommand, AddressOf OnExecuteSend, AddressOf OnCanExecuteSend))

            Me._win.CommandBindings.Add(New CommandBinding(iConverterCommands.ProcessCommand, AddressOf OnExecuteProcess, AddressOf OnCanExecuteProcess))


        End Sub








#Region "ShowVersionAndCopyRightInfoCommand 命令"

        Private Sub OnCanExecuteShowVersionAndCopyRightInfoCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = True
            e.Handled = True

        End Sub

        Private Sub OnExecuteShowVersionAndCopyRightInfoCommand(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            Dim wind As New AboutWindow
            wind.Owner = Me._win
            wind.ShowDialog()


            e.Handled = True
        End Sub

#End Region





#Region "ShowLicenseInfoCommand 命令"

        Private Sub OnCanExecuteShowLicenseInfoCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = True
            e.Handled = True

        End Sub

        Private Sub OnExecuteShowLicenseInfoCommand(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            Dim wind As New LicenseWindow
            wind.Owner = Me._win
            wind.ShowDialog()

            e.Handled = True
        End Sub

#End Region





#Region "SettingsCommand 命令"

        Private Sub OnCanExecuteSettingsCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = True
            e.Handled = True

        End Sub

        Private Sub OnExecuteSettingsCommand(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)


            Dim wind As New OptionWindow

            If e.Parameter IsNot Nothing AndAlso TypeOf e.Parameter Is OptionTabs Then
                Dim ot As OptionTabs = e.Parameter

                Select Case ot
                    Case OptionTabs.General

                    Case OptionTabs.Encodings
                        wind.tabOption.SelectedIndex = 1
                    Case OptionTabs.Plugins
                        wind.tabOption.SelectedIndex = 2
                    Case OptionTabs.Conversion
                        wind.tabOption.SelectedIndex = 3
                        'Case OptionTabs.Send
                        '    wind.tabOption.SelectedIndex = 4
                    Case OptionTabs.Batch
                        wind.tabOption.SelectedIndex = 4

                End Select
            End If

            wind.Owner = Me._win


            wind.ShowDialog()


            e.Handled = True
        End Sub

#End Region



#Region " 转换和批量转换  命令"



#Region " Convert  命令"


        Private Sub OnCanExecuteConvertCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = Me.IsSelectDocument
            e.Handled = True
        End Sub


        Private Sub OnExecuteConvertCommand(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            If Me.IsSelectDocument Then
                UpdateConverter()

                _converter.Convert(Me.SelectDocument)

                e.Handled = True
            End If
        End Sub


#End Region

        ''' <summary>
        ''' 全局编码转换器
        ''' </summary>
        ''' <remarks></remarks>
        Private _converter As EncodingConverter

        ''' <summary>
        ''' 更新编码器
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub UpdateConverter()
            If _converter Is Nothing Then
                _converter = New EncodingConverter()
            End If

            '更新转换器插件设置
            Dim procerss As IEnumerable(Of Processer)
            Dim send As Extensions.Send

            If Me.IsAutoUsePostProcessings Then

                procerss = From pp In PluginsManager.PostProcessings,
                           p In pp.Processings
                           Where p.isSelected
                           Select p

            Else
                '清空插件
                procerss = Nothing

            End If

            If Me.IsAutoUseSend Then
                '发送到插件


                send = (From item In Me.PluginSendMenuItems
                        Let s = TryCast(item.DataContext, Send)
                        Where item.IsChecked AndAlso s IsNot Nothing
                        Select s).FirstOrDefault



            Else
                send = Nothing
            End If


            Me._converter.SetPlugins(procerss, send)
        End Sub

#Region "BatchConvertCommand 命令"

        Private Sub OnCanExecuteBatchConvertCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = Me.IsSelectDocument AndAlso Me.isHaveMoreDocuments
            e.Handled = True
        End Sub

        Private Sub OnExecuteBatchConvertCommand(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            UpdateConverter()

            Dim closedocs As New List(Of ConvertDocument)

            Dim source = Me.SelectDocument.SourceEncoding
            Dim des = Me.SelectDocument.DestinationEncoding


            For Each doc In Me.DocumentCollection

                doc.SourceEncoding = source
                doc.DestinationEncoding = des


                _converter.Convert(doc)
                If SettingManager.Settings.isBatchConvertAfterAutoClose Then
                    closedocs.Add(doc)
                End If
            Next


            If SettingManager.Settings.isBatchConvertAfterAutoClose Then

                For Each doc In closedocs
                    CloseDoucment(doc)
                Next
            End If


            e.Handled = True
        End Sub

#End Region


#End Region






#Region "Copy 命令"

        Private Sub OnCanExecuteCopy(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = Me.IsSelectDocument
            e.Handled = True
        End Sub

        Private Sub OnExecuteCopy(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            ' Perform the actions associated with the command.
            ' Remove this exception after the appropriate code is added.
            Throw New NotImplementedException()

            ' Work was done for this command. Mark the event as handled.
            e.Handled = True
        End Sub

#End Region





#Region "Paste 命令"

        Private Sub OnCanExecutePaste(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = True
            e.Handled = True

        End Sub

        Private Sub OnExecutePaste(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            ' Perform the actions associated with the command.
            ' Remove this exception after the appropriate code is added.
            Throw New NotImplementedException()

            ' Work was done for this command. Mark the event as handled.
            e.Handled = True
        End Sub

#End Region









#Region "Open 命令"

        Private Sub OnCanExecuteOpen(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = True

        End Sub

        Private Sub OnExecuteOpen(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)


            Dim dlg As New Microsoft.Win32.OpenFileDialog()
            '  dlg.FileName = ""
            dlg.DefaultExt = ".txt"
            dlg.Filter = FileExtensionManager.Filter

            If dlg.ShowDialog Then
                Dim filename = dlg.FileName

                OpenDocument(filename)


            End If



            e.Handled = True
        End Sub

#End Region



        ''' <summary>
        ''' 打开文档
        ''' </summary>
        ''' <param name="filename">要打开的文件</param>
        ''' <remarks></remarks>
        Private Sub OpenDocument(ByVal filename As String)
            If Not IO.File.Exists(filename) Then Return

            '检查文件扩展名 是否 适合打开

            If FileExtensionManager.IsNotbeOpendFileExtension(filename) Then
                '不应该打开的文件
                'TODO:自定义对话框
                MessageBox.Show(String.Format("程序检测到不应该打开的文件：{0} 请确保选择正确文件类型。", filename), "打开消息", MessageBoxButton.OK)
            Else
                '如果文件不是已知类型，则询问是否打开
                If Not FileExtensionManager.IsKnowFileExtension(filename) AndAlso
                    MessageBox.Show(String.Format("程序不知道文件（{0}）的类型，如果继续打开可能会有意外结果，是否仍要打开？", filename),
                                    "打开消息", MessageBoxButton.YesNo) = MessageBoxResult.No Then
                    Return
                End If

                Dim doc = ConvertDocumentFactory.CreateFromFile(filename)

                Me._documentCollection.Add(doc)

                SetSelectDocument(doc)

            End If
        End Sub


        ''' <summary>
        ''' 设置选定的文档
        ''' </summary>
        ''' <param name="doc">要选定的文档</param>
        ''' <remarks></remarks>
        Private Sub SetSelectDocument(ByVal doc As ConvertDocument)
            If Me._documentCollection.Count > 0 Then
                Me.SelectDocumentIndex = Me._documentCollection.IndexOf(doc)
            End If
        End Sub


#Region "New 命令"

        Dim _num As Integer = 0


        Private Sub OnCanExecuteNew(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = True
            e.Handled = True
        End Sub

        Private Sub OnExecuteNew(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)


            Dim doc = ConvertDocumentFactory.CreateNew
            doc.Name = String.Format("Test {0}", Interlocked.Increment(Me._num))
            Me._documentCollection.Add(doc)

            SetSelectDocument(doc)

            e.Handled = True
        End Sub

#End Region





#Region "Close 命令"

        Private Sub OnCanExecuteClose(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = If(e.Parameter Is Nothing, Me.IsSelectDocument, TypeOf e.Parameter Is ConvertDocument)


            e.Handled = True

        End Sub

        Private Sub OnExecuteClose(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            Dim CanExecute = If(e.Parameter Is Nothing, Me.IsSelectDocument, TypeOf e.Parameter Is ConvertDocument)


            If CanExecute Then


                Dim doc As ConvertDocument = If(e.Parameter Is Nothing, Me.SelectDocument, DirectCast(e.Parameter, ConvertDocument))


                CloseDoucment(doc)



                e.Handled = True
            End If

        End Sub

        ''' <summary>
        ''' 关闭文档
        ''' </summary>
        ''' <param name="doc">要操作的文档</param>
        ''' <remarks></remarks>
        Private Function CloseDoucment(ByVal doc As ConvertDocument) As MessageBoxResult

            '流程说明
            '当文档没有被修改时， 直接关闭文档
            '当文档已修改，并且选择 
            '    Yes ，   保存文档， 并关闭
            '    No  ，   关闭文档
            '    Cancel ,  直接返回

            Dim result As MessageBoxResult = MessageBoxResult.None

            If doc.IsChanged Then

                result = MessageBox.Show(String.Format("文档 {0} 已经修改，请问是否保存？", doc.Name),
                                                                             "询问", MessageBoxButton.YesNoCancel, MessageBoxImage.Question,
                                                                             MessageBoxResult.Yes)

                Select Case result
                    Case MessageBoxResult.Yes
                        If result = MessageBoxResult.Yes Then
                            SaveDocument(doc)
                        End If
                    Case MessageBoxResult.No

                    Case MessageBoxResult.Cancel
                        Return result
                End Select
            End If

            Me._documentCollection.Remove(doc)
            Return result
        End Function
#End Region



#Region " Save  Docment "



#Region "Save 命令"

        Private Sub OnCanExecuteSave(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            e.CanExecute = Me.IsSelectDocument
            e.Handled = True

        End Sub

        Private Sub OnExecuteSave(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            If Me.IsSelectDocument AndAlso Me.SelectDocument.IsChanged Then

                Dim doc = Me.SelectDocument

                SaveDocument(doc)



                e.Handled = True

            End If
        End Sub

#End Region



#Region "SaveAs 命令"

        Private Sub OnCanExecuteSaveAs(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = Me.IsSelectDocument
            e.Handled = True
        End Sub

        Private Sub OnExecuteSaveAs(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            If Me.IsSelectDocument Then

                Dim doc = Me.SelectDocument

                SaveAsDocument(doc)



                e.Handled = True

            End If
        End Sub

#End Region



#Region "SaveADV 命令"

        Private Sub OnCanExecuteSaveADV(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = Me.IsSelectDocument AndAlso e.Parameter IsNot Nothing AndAlso TypeOf e.Parameter Is Encoding
            e.Handled = True
        End Sub

        Private Sub OnExecuteSaveADV(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            If Me.IsSelectDocument AndAlso e.Parameter IsNot Nothing AndAlso TypeOf e.Parameter Is Encoding Then

                Dim doc = Me.SelectDocument

                SaveAsDocument(doc, e.Parameter)



                e.Handled = True

            End If
        End Sub

#End Region


        ''' <summary>
        ''' 保存文档
        ''' </summary>
        ''' <param name="doc"></param>
        ''' <remarks></remarks>
        Private Shared Sub SaveDocument(ByVal doc As ConvertDocument)
            If doc.IsFromFile Then

                doc.Save(SettingManager.Settings.isBackupSaveDocument)

            Else

                SaveAsDocument(doc)

            End If
        End Sub
        ''' <summary>
        ''' 另存为文档
        ''' </summary>
        ''' <param name="doc">要保存的文档</param>
        ''' <param name="encoding">要保存的编码</param>
        ''' <remarks></remarks>
        Private Shared Sub SaveAsDocument(ByVal doc As ConvertDocument, Optional ByVal encoding As Encoding = Nothing)
            ' Configure save file dialog box
            Dim dlg As New Microsoft.Win32.SaveFileDialog()
            dlg.FileName = doc.Name
            dlg.DefaultExt = ".txt"
            dlg.Filter = FileExtensionManager.Filter

            If dlg.ShowDialog Then
                Dim filename = dlg.FileName

                '另存为的不需要备份


                If encoding Is Nothing Then
                    doc.SaveToFile(False, filename)
                Else
                    doc.SaveToFileWithEncoding(False, filename, encoding)
                End If


            End If
        End Sub



#End Region



#Region "OpenLink 命令"

        Private Sub OnCanExecuteOpenLink(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = True ' e.Parameter IsNot Nothing AndAlso TypeOf e.Parameter Is String AndAlso not  String.IsNullOrEmpty(e.Parameter)
            e.Handled = True

        End Sub

        Private Sub OnExecuteOpenLink(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
            'e.Parameter IsNot Nothing AndAlso
            If TypeOf e.Parameter Is String AndAlso Not String.IsNullOrEmpty(e.Parameter) Then

                Process.Start(e.Parameter)

                e.Handled = True
            End If

        End Sub

#End Region






#Region "Exit 命令"

        Private Sub OnCanExecuteExit(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
            e.CanExecute = True
            e.Handled = True

        End Sub

        Private Sub OnExecuteExit(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            Dim CloseDocumentResult As System.Windows.MessageBoxResult = CloseAllDocument()


            If CloseDocumentResult <> MessageBoxResult.Cancel Then Application.Current.Shutdown()

            e.Handled = True
        End Sub

#End Region

        ''' <summary>
        ''' 关闭所有文档
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function CloseAllDocument() As System.Windows.MessageBoxResult
            Do Until Me.DocumentCollection.Count = 0
                Dim result = CloseDoucment(Me.DocumentCollection(0))
                If result = MessageBoxResult.Cancel Then

                    Return result
                End If
            Loop
            Return MessageBoxResult.None
        End Function






#Region "Send 命令"

        Private Sub OnCanExecuteSend(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            Dim send = TryCast(e.Parameter, Send)

            e.CanExecute = Me.IsSelectDocument AndAlso send IsNot Nothing AndAlso send.CheckCanRun
            e.Handled = True

        End Sub

        Private Sub OnExecuteSend(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)


            Dim send = TryCast(e.Parameter, Send)

            If Me.IsSelectDocument AndAlso send IsNot Nothing AndAlso send.CheckCanRun Then
                send.SendTo(Me.SelectDocument)

            End If

            e.Handled = True
        End Sub

#End Region







#Region "Process 命令"

        Private Sub OnCanExecuteProcess(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)

            Dim p = TryCast(e.Parameter, Processer)


            e.CanExecute = Me.IsSelectDocument AndAlso p IsNot Nothing

            e.Handled = True

        End Sub

        Private Sub OnExecuteProcess(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)

            Dim p = TryCast(e.Parameter, Processer)


            If Me.IsSelectDocument AndAlso p IsNot Nothing Then

                p.Processing(Me.SelectDocument)

                e.Handled = True
            End If


        End Sub

#End Region







    End Class

End Namespace

